/**
 *  一、promise实例对象
 *      1. PromiseState='pending'
 *      2. PromiseResult=undefined;
 * 
 *  二、改变promise状态的三种途径：
 * 
 *  1. resolve(成功结果值)
 *  2. reject(失败的结果值)
 *  3. throw 失败的结果值
 * 
 *  三、状态只能改变一次：
 *  1. 在改变状态之前判断，是不是pending，如果是才改，不是退出
 *  
 *  四、then方法
 *  1. 定义在原型对象上： 所有的Promise实例对象都可以调用
 *  2. 要定义成普通方法，确保this指向当前实力对象
 * 
 *  
 * 
 * 
 *  
 */
 function Promise(executor){
    this.PromiseState = 'pending';
    this.PromiseResult = undefined;
    // 要定义成箭头函数，确保函数内this指向当前promise实例对象
    const resolve = (value)=>{ 
        console.log(this);
        if(this.PromiseState !== 'pending') return;
        // 1. 改变promise的状态为 fulfilled
        // 2. 设置结果值
        this.PromiseState = 'fulfilled';
        this.PromiseResult = value;
        // 执行所有的成功的回调
        // debugger;
        if(Promise.callbacks.length){
            Promise.callbacks.forEach(item=>{
                item.success();
            })
        }
    }
    const reject = (reason)=>{
        if(this.PromiseState !== 'pending') return;
        // 1. 改变promise的状态为 rejected
        // 2. 设置失败的结果值
        this.PromiseState = 'rejected';
        this.PromiseResult = reason;
        if(Promise.callbacks.length){
            Promise.callbacks.forEach(item=>{
                item.fail();
            })
        }
    }
    try{
        executor(resolve, reject);
    }catch(e){
        reject(e);
        console.error(e);
    }
}

Promise.callbacks = []

Promise.prototype.then = function(onResolve, onReject){
    // 1. promise: fulfilled 执行 onResolve
    // 2. promise: rejected  执行 onReject
    // 3. 如果是异步改变的状态 pending 该怎么办？
    if(this.PromiseState === 'fulfilled'){
        onResolve(this.PromiseResult);
    }
    if(this.PromiseState === 'rejected'){
        onReject(this.PromiseResult);
    }
    if(this.PromiseState === 'pending'){
        // 不能够执行成功的回调，也不能执行失败的回调。需要等状态确定的时候决定执行谁
        // 将成功和失败的回调存储在 当前实例的属性 callbacks身上
        Promise.callbacks.push({
            success:()=>{
                onResolve(this.PromiseResult);
            },
            fail:()=>{
                onReject(this.PromiseResult);
            }
        })
    }
}